import colorsys
import os
import random

import cv2
import pdfplumber
import numpy as np

from find_blank import get_contours


# 选取密集关键点
def dense(image, flag_image, step=10, radius=[8]):
    kps = []
    for x in range(1, image.shape[1], step):
        for y in range(1, image.shape[0], step):
            if flag_image[y][x][0] == 0 and flag_image[y][x][1] == 0 and flag_image[y][x][2] == 255:
                kps.append(cv2.KeyPoint(x, y, radius * 2))

    return kps


def equal(a, b, T=160):
    if np.linalg.norm(a-b) <= T:
        return True
    else:
        return False


def find_lckeypoints(s1, s2): 
	# 生成字符串长度加1的0矩阵，m用来保存对应位置匹配的结果
    m = [ [ 0 for x in range(len(s2)+1) ] for y in range(len(s1)+1) ] 
    # d用来记录转移方向
    d = [ [ None for x in range(len(s2)+1) ] for y in range(len(s1)+1) ] 
 
    for p1 in range(len(s1)): 
        for p2 in range(len(s2)):
            #字符匹配成功，则该位置的值为左上方的值加1
            if equal(s1[p1],s2[p2]): 
                # print("Calculate distance of des1[{}] & des2[{}]".format(p1, p2))
                m[p1+1][p2+1] = m[p1][p2]+1
                d[p1+1][p2+1] = 'ok'
            #左值大于上值，则该位置的值为左值，并标记回溯时的方向
            elif m[p1+1][p2] > m[p1][p2+1]: 
                m[p1+1][p2+1] = m[p1+1][p2]
                d[p1+1][p2+1] = 'left'
            #上值大于左值，则该位置的值为上值，并标记方向up
            else: 
                m[p1+1][p2+1] = m[p1][p2+1]
                d[p1+1][p2+1] = 'up'
    (p1, p2) = (len(s1), len(s2)) 

    s = []
    comman_index1 = []
    comman_index2 = []
    while m[p1][p2]: #不为None时
        c = d[p1][p2]
        if c == 'ok': #匹配成功，插入该字符，并向左上角找下一个
            s.append(s1[p1-1])
            comman_index1.append(p1-1)
            comman_index2.append(p2-1)
            p1-=1
            p2-=1 
        if c =='left':  #根据标记，向左找下一个
            p2 -= 1
        if c == 'up':   #根据标记，向上找下一个
            p1 -= 1
    s.reverse()
    comman_index1.reverse()
    comman_index2.reverse()
    return s, comman_index1, comman_index2


if __name__ == "__main__":

    # 要对比的两张图像路径
    image_path = "images"
    image_name1 = "test_Page1.png"
    image_name2 = "test_Page2.png"

    get_contours(image_path=image_path,
                 image_name=image_name1)

    get_contours(image_path=image_path,
                 image_name=image_name2)

    flag_image_name1 = "flag_images/test_Page1_flag.png"
    flag_image_name2 = "flag_images/test_Page2_flag.png"

    image1 = cv2.imread(os.path.join(image_path, image_name1))
    image2 = cv2.imread(os.path.join(image_path, image_name2))

    image1_copy = image1.copy()
    image2_copy = image2.copy()

    flag_image1 = cv2.imread(flag_image_name1)
    flag_image2 = cv2.imread(flag_image_name2)

    DENSE_STEP = 8 # 间隔的像素个数

    # 设置sift算子
    sift = cv2.xfeatures2d.SIFT_create()

    # 获取密集点
    kps1 = dense(image1, flag_image1, DENSE_STEP, 8)
    kps2 = dense(image2, flag_image2, DENSE_STEP, 8)

    # 计算密集描述符
    kps1, des1 = sift.compute(image1, kps1)
    kps2, des2 = sift.compute(image2, kps2)

    image3 = cv2.drawKeypoints(image1, kps1, None, color=[0, 0, 255])
    image4 = cv2.drawKeypoints(image2, kps2, None, color=[0, 0, 255])
    cv2.imwrite("Keypoints.png", np.hstack([image3, image4]))

    print("Number of key points: Image1:{}, Image2:{}".format(len(kps1), len(kps2)))

    _, kp1_index, kp2_index = find_lckeypoints(des1, des2)
    good_kps1 = []
    good_kps2 = []
    for i in kp1_index:
        good_kps1.append(kps1[i])
    for i in kp2_index:
        good_kps2.append(kps2[i])
    print("Length of good kps1:{} & good kps2:{}".format(len(good_kps1), len(good_kps2)))
    image5 = cv2.drawKeypoints(image1_copy, good_kps1, None, color=[0, 0, 255])
    image6 = cv2.drawKeypoints(image2_copy, good_kps2, None, color=[0, 0, 255])
    cv2.imwrite("No_change.png", np.hstack([image5, image6]))